<!DOCTYPE html>
<html lang="en">
  <head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover"/>
 
<link rel="stylesheet" href="../assets/css/style.css"/> 
<!-- Copyright 1998-2021 by Northwoods Software Corporation. -->    <title> GoJS Buttons -- Northwoods Software </title>
    <link rel="stylesheet" href="../assets/css/prism.css"  />
  </head>
  <script>
    
    window.diagrams = [];
    window.goCode = function(pre, w, h, parentid, animation) {
      window.diagrams.push([pre, w, h, parentid, animation]);
    }
  </script>
  <body>
  <nav id="navTop" class="w-full z-30 top-0 text-white bg-nwoods-primary">
    <div class="w-full container max-w-screen-lg mx-auto flex flex-wrap sm:flex-nowrap items-center justify-between mt-0 py-2">
      <div class="md:pl-4">
        <a class="text-white hover:text-white no-underline hover:no-underline
        font-bold text-2xl lg:text-4xl rounded-lg hover:bg-nwoods-secondary " href="../">
          <h1 class="mb-0 p-1 ">GoJS</h1>
        </a>
      </div>
      <button id="topnavButton" class="rounded-lg sm:hidden focus:outline-none focus:ring" aria-label="Navigation">
        <svg fill="currentColor" viewBox="0 0 20 20" class="w-6 h-6">
          <path id="topnavOpen" fill-rule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM9 15a1 1 0 011-1h6a1 1 0 110 2h-6a1 1 0 01-1-1z" clip-rule="evenodd"></path>
          <path id="topnavClosed" class="hidden" fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
        </svg>
      </button>
      <div id="topnavList" class="hidden lg:text-base sm:block items-center w-auto mt-0 text-white p-0 z-20">
        <ul class="list-reset list-none font-semibold flex justify-end flex-wrap sm:flex-nowrap items-center px-0 pb-0">
          <li class="p-1 sm:p-0"><a class="topnav-link" href="../learn/">Learn</a></li>
          <li class="p-1 sm:p-0"><a class="topnav-link" href="../samples/">Samples</a></li>
          <li class="p-1 sm:p-0"><a class="topnav-link" href="../intro/">Intro</a></li>
          <li class="p-1 sm:p-0"><a class="topnav-link" href="../api/">API</a></li>
          <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/products/register.html">Register</a></li>
          <li class="p-1 sm:p-0"><a class="topnav-link" href="../download.html">Download</a></li>
          <li class="p-1 sm:p-0"><a class="topnav-link" href="https://forum.nwoods.com/c/gojs/11">Forum</a></li>
          <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/contact.html"
           target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a></li>
          <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/sales/index.html"
           target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a></li>
        </ul>
      </div>
    </div>
    <hr class="border-b border-gray-600 opacity-50 my-0 py-0" />
  </nav>
    
    <div class="md:flex flex-col md:flex-row md:min-h-screen w-full max-w-screen-xl mx-auto">
      
    <div id="navSide" class="flex flex-col w-full md:w-40 lg:w-48 text-gray-700 bg-white flex-shrink-0">
      <div class="flex-shrink-0 px-8 py-4">
        <button id="navButton" class="rounded-lg md:hidden focus:outline-none focus:ring" aria-label="Navigation">
          <svg fill="currentColor" viewBox="0 0 20 20" class="w-6 h-6">
            <path id="navOpen" fill-rule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM9 15a1 1 0 011-1h6a1 1 0 110 2h-6a1 1 0 01-1-1z" clip-rule="evenodd"></path>
            <path id="navClosed" class="hidden" fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
          </svg>
        </button>
      </div>
      <nav id="navList" class="min-h-screen hidden md:block sidebar-nav flex-grow px-1 lg:px-4 pb-4 md:pb-0 md:overflow-y-auto break-words">
  <a href="index.html">Basics</a>
  <a href="buildingObjects.html">Building Parts</a>
  <a href="usingModels.html">Using Models</a>
  <a href="dataBinding.html">Data Binding</a>
  <a href="react.html">GoJS with React</a>
  <a href="angular.html">GoJS with Angular</a>
  <a href="textBlocks.html">TextBlocks</a>
  <a href="shapes.html">Shapes</a>
  <a href="pictures.html">Pictures</a>
  <a href="panels.html">Panels</a>
  <a href="tablePanels.html">Table Panels</a>
  <a href="brush.html">Brushes</a>
  <a href="sizing.html">Sizing Objects</a>
  <a href="itemArrays.html">Item Arrays</a>
  <a href="changedEvents.html">Changed Events</a>
  <a href="transactions.html">Transactions</a>
  <a href="viewport.html">Coordinates</a>
  <a href="initialView.html">Initial View</a>
  <a href="collections.html">Collections</a>
  <a href="links.html">Links</a>
  <a href="linkLabels.html">Link Labels</a>
  <a href="connectionPoints.html">Link Points</a>
  <a href="ports.html">Ports</a>
  <a href="nodes.html">Nodes</a>
  <a href="debugging.html">Debugging</a>
  <a href="layouts.html">Layouts</a>
  <a href="trees.html">Trees</a>
  <a href="subtrees.html">SubTrees</a>
  <a href="groups.html">Groups</a>
  <a href="subgraphs.html">SubGraphs</a>
  <a href="sizedGroups.html">Sized Groups</a>
  <a href="selection.html">Selection</a>
  <a href="highlighting.html">Highlighting</a>
  <a href="animation.html">Animation</a>
  <a href="toolTips.html">ToolTips</a>
  <a href="contextmenus.html">Context Menus</a>
  <a href="events.html">Diagram Events</a>
  <a href="tools.html">Tools</a>
  <a href="commands.html">Commands</a>
  <a href="permissions.html">Permissions</a>
  <a href="validation.html">Validation</a>
  <a href="HTMLInteraction.html">HTML Interaction</a>
  <a href="layers.html">Layers &amp; Z-ordering</a>
  <a href="palette.html">Palette</a>
  <a href="overview.html">Overview</a>
  <a href="resizing.html">Resizing Diagrams</a>
  <a href="replacingDeleting.html">Replacing and Deleting</a>
  <a href="buttons.html">Buttons</a>
  <a href="templateMaps.html">Template Maps</a>
  <a href="legends.html">Legends and Titles</a>
  <a href="extensions.html">Extensions</a>
  <a href="geometry.html">Geometry Strings</a>
  <a href="grids.html">Grid Patterns</a>
  <a href="graduatedPanels.html">Graduated Panels</a>
  <a href="makingImages.html">Diagram Images</a>
  <a href="makingSVG.html">Diagram SVG</a>
  <a href="printing.html">Printing</a>
  <a href="serverSideImages.html">Server-side Images</a>
  <a href="nodeScript.html">GoJS in Node.js</a>
  <a href="testing.html">Testing</a>
  <a href="storage.html">Storage</a>
  <a href="performance.html">Performance</a>
  <a href="source.html">Building from Source</a>
  <a href="platforms.html">Platforms</a>
  <a href="deployment.html">Deployment</a>
      </nav>
    </div>      
      <div class="pt-4 px-2 md:px-0 lg:px-4 pb-16 w-full overflow-hidden">




<h1>Buttons</h1>
<p>
For your convenience we have defined several <a>Panel</a>s for common uses.
These include "Button", "TreeExpanderButton", "SubGraphExpanderButton", "PanelExpanderButton", "ContextMenuButton", and "CheckBoxButton".
"ContextMenuButton"s are typically used inside of "ContextMenu" Panels;
"CheckBoxButton"s are used in the implementation of "CheckBox" Panels.
</p>
<p>
These predefined panels can be used as if they were <a>Panel</a>-derived classes in calls to <a>GraphObject,make</a>.
They are implemented as simple visual trees of <a>GraphObject</a>s in <a>Panel</a>s,
with pre-set properties and event handlers.
</p>
<p>
You can see a copy of their definitions in this file:
<a href="../extensions/Buttons.js">Buttons.js</a>.
</p>
<p>
See samples that make use of buttons in the <a href="../samples/index.html#buttons">samples index</a>.
In addition, see the <a href="../extensions/Checkboxes.html">Checkboxes</a> extension for an example of using "CheckBoxButton".
</p>


<h2 id="GeneralButtons">General Buttons</h2>
<p>
The most general kind of predefined <a>Panel</a> is "Button".
</p>
<pre class="lang-js" id="button"><code>
  diagram.nodeTemplate =
    $(go.Node, "Auto",
      { locationSpot: go.Spot.Center },
      $(go.Shape, "Rectangle",
        { fill: "gold" }),
      $(go.Panel, "Vertical",
        { margin: 3 },
        $("Button",
          { margin: 2,
            click: incrementCounter },
          $(go.TextBlock, "Click me!")),
        $(go.TextBlock,
          new go.Binding("text", "clickCount",
                         function(c) { return "Clicked " + c + " times."; }))
      )
    );

  function incrementCounter(e, obj) {
    var node = obj.part;
    var data = node.data;
    if (data && typeof(data.clickCount) === "number") {
      node.diagram.model.commit(function(m) {
        m.set(data, "clickCount", data.clickCount + 1);
      }, "clicked");
    }
  }

  diagram.model = new go.GraphLinksModel(
    [ { clickCount: 0 } ]);
</code></pre>
<script>goCode("button", 600, 150)</script>

<p>
Buttons are just Panels holding a Shape that will surround whatever content you give it.
The border Shape is named "ButtonBorder" so that you can easily set or bind its properties.
</p>
<p>
The event handlers defined by all "Button"s make use of additional properties,
not defined in the API, but that you can see in the definition of "Button":
<a href="../extensions/Buttons.js">Buttons.js</a>.
These properties parameterize the appearance of the button.
</p>
<pre class="lang-js" id="button2"><code>
  diagram.nodeTemplate =
    $(go.Node, "Auto",
      { locationSpot: go.Spot.Center },
      $(go.Shape, "Rectangle",
        { fill: "gold" }),
      $(go.Panel, "Vertical",
        { margin: 3 },
        $("Button",
          {
            margin: 2,
            // set properties on the border Shape of the "Button"
            "ButtonBorder.fill": "fuchsia",
            // set properties on the "Button" itself used by its event handlers
            "_buttonFillOver": "pink",
            click: function(e, button) { alert(button.findObject("ButtonBorder").fill); }
          },
          $(go.TextBlock, "fuchsia button\nwith pink highlight", { margin: 2, textAlign: "center" })
        ),
        $("Button",
          {
            margin: 2,
            // set properties on the border Shape of the "Button"
            "ButtonBorder.figure": "Circle",
            "ButtonBorder.fill": "cyan",
            "ButtonBorder.stroke": "darkcyan",
            "ButtonBorder.strokeWidth": 3,
            // set properties on the "Button" itself used by its event handlers
            "_buttonFillOver": "white",
            "_buttonStrokeOver": "cyan",
            "_buttonFillPressed": "lightgray",
            click: function(e, button) { alert(button.findObject("ButtonBorder").stroke); }
          },
          $(go.TextBlock, "Circular\nbutton", { margin: 2, textAlign: "center" })
        ),
        $("Button",
          {
            margin: 2,
            click: function(e, button) { alert(button.findObject("PIC").source); }
          },
          // the button content can be anything -- it doesn't have to be a TextBlock
          $(go.Picture, "images/50x40.png", { name: "PIC", width: 50, height: 40 })
        ),
        $("Button",
          {
            margin: 2,
            // buttons can be disabled too, by either setting or data binding:
            isEnabled: false,
            click: function(e, button) { alert("won't be alerted"); }
          },
          $(go.TextBlock, "disabled", { stroke: "gray" })
        )
      )
    );

  diagram.model = new go.GraphLinksModel([ { } ]);
</code></pre>
<script>goCode("button2", 600, 250)</script>


<h2 id="TreeExpanderButtons">TreeExpanderButtons</h2>
<p>
It is common to want to expand and collapse subtrees.
It is easy to let the user control this by adding an instance of the "TreeExpanderButton" to your node template.
The button calls <a>CommandHandler.collapseTree</a> or <a>CommandHandler.expandTree</a>
depending on the value of <a>Node.isTreeExpanded</a>.
The button's icon's <a>Shape.figure</a> changes as the value of
<a>Node.isTreeExpanded</a> changes.
</p>
<pre class="lang-js" id="treeExpanderButton"><code>
  diagram.nodeTemplate =
    $(go.Node, "Spot",
      $(go.Panel, "Auto",
        $(go.Shape, "Rectangle",
          { fill: "gold" }),
        $(go.TextBlock, "Click small button\nto collapse/expand subtree",
          { margin: 5 })
      ),
      $("TreeExpanderButton",
        { alignment: go.Spot.Bottom, alignmentFocus: go.Spot.Top },
        { visible: true })
    );

  diagram.layout = $(go.TreeLayout, { angle: 90 });

  diagram.model = new go.GraphLinksModel(
    [ { key: 1 },
      { key: 2 } ],
    [ { from: 1, to: 2 } ] );
</code></pre>
<script>goCode("treeExpanderButton", 600, 200)</script>

<p>
A "TreeExpanderButton" is a "Button" that holds a Shape displaying either a "MinusLine" or a "PlusLine"
figure, depending on the value of the <a>Node.isTreeExpanded</a>.
That shape is named "ButtonIcon", so that you can easily set or bind its properties,
in addition to the properties of the "ButtonBorder" and of the "Button" itself.
</p>
<pre class="lang-js" id="treeExpanderButton2"><code>
  diagram.nodeTemplate =
    $(go.Node, "Spot",
      $(go.Panel, "Auto",
        $(go.Shape, "Rectangle",
          { fill: "gold" }),
        $(go.TextBlock, "Click small button\nto collapse/expand subtree",
          { margin: 5 })
      ),
      $("TreeExpanderButton",
        {
          // set the two additional properties used by "TreeExpanderButton"
          // that control the shape depending on the value of Node.isTreeExpanded
          "_treeExpandedFigure": "TriangleUp",
          "_treeCollapsedFigure": "TriangleDown",
          // set properties on the icon within the border
          "ButtonIcon.fill": "darkcyan",
          "ButtonIcon.strokeWidth": 0,
          // set general "Button" properties
          "ButtonBorder.figure": "Circle",
          "ButtonBorder.stroke": "darkcyan",
          "_buttonStrokeOver": "darkcyan"
        },
        { alignment: go.Spot.Bottom, alignmentFocus: go.Spot.Top },
        { visible: true })
    );

  diagram.layout = $(go.TreeLayout, { angle: 90 });

  diagram.model = new go.GraphLinksModel(
    [ { key: 1 },
      { key: 2 } ],
    [ { from: 1, to: 2 } ] );
</code></pre>
<script>goCode("treeExpanderButton2", 600, 200)</script>


<h2 id="SubGraphExpanderButtons">SubGraphExpanderButtons</h2>
<p>
It is also common to want to expand and collapse groups containing subgraphs.
You can let the user control this by adding an instance of the "SubGraphExpanderButton" to your group template.
The button calls <a>CommandHandler.collapseSubGraph</a> or <a>CommandHandler.expandSubGraph</a>
depending on the value of <a>Group.isSubGraphExpanded</a>.
The button's icon's <a>Shape.figure</a> changes as the value of
<a>Group.isSubGraphExpanded</a> changes.
</p>
<pre class="lang-js" id="subgraphExpanderButton"><code>
  diagram.groupTemplate =
    $(go.Group, "Auto",
      $(go.Shape, "Rectangle",
        { fill: "gold" }),
      $(go.Panel, "Vertical",
        { margin: 5,
          defaultAlignment: go.Spot.Left },
        $(go.Panel, "Horizontal",
          $("SubGraphExpanderButton",
            { margin: new go.Margin(0, 3, 5, 0) }),
          $(go.TextBlock, "Group")
        ),
        $(go.Placeholder)
      )
    );

  diagram.model = new go.GraphLinksModel(
    [ { key: 0, isGroup: true },
      { key: 1, group: 0 },
      { key: 2, group: 0 },
      { key: 3, group: 0 } ] );
</code></pre>
<script>goCode("subgraphExpanderButton", 600, 150)</script>

<p>
A "SubGraphExpanderButton" is like a "TreeExpanderButton" in its being a "Button"
with a border Shape surrounding an icon Shape.
That shape is named "ButtonIcon", so that you can easily set or bind its properties,
in addition to the properties of the "ButtonBorder" and of the "Button" itself.
</p>
<pre class="lang-js" id="subgraphExpanderButton2"><code>
  diagram.groupTemplate =
    $(go.Group, "Auto",
      $(go.Shape, "Rectangle",
        { fill: "gold" }),
      $(go.Panel, "Vertical",
        { margin: 5,
          defaultAlignment: go.Spot.Left },
        $(go.Panel, "Horizontal",
          $("SubGraphExpanderButton",
            {
              // set the two additional properties used by "SubGraphExpanderButton"
              // that control the shape depending on the value of Group.isSubGraphExpanded
              "_subGraphExpandedFigure": "TriangleUp",
              "_subGraphCollapsedFigure": "TriangleDown",
              // set other properties on the button icon
              "ButtonIcon.angle": -45,
              // and properties on the button border or the button itself
              "ButtonBorder.opacity": 0.0
            }),
          $(go.TextBlock, "Group")
        ),
        $(go.Placeholder)
      )
    );

  diagram.model = new go.GraphLinksModel(
    [ { key: 0, isGroup: true },
      { key: 1, group: 0 },
      { key: 2, group: 0 },
      { key: 3, group: 0 } ] );
</code></pre>
<script>goCode("subgraphExpanderButton2", 600, 150)</script>


<h2 id="PanelExpanderButtons">PanelExpanderButtons</h2>
<p>
It is common to want to expand and collapse a piece of a node,
thereby showing or hiding details that are sometimes not needed.
It is easy to let the user control this by adding an instance of the "PanelExpanderButton" to your node template.
The second argument to <a>GraphObject,make</a> should be a string that names the element in the node whose
<a>GraphObject.visible</a> property you want the button to toggle.
</p>
<pre class="lang-js" id="panelExpanderButton"><code>
  diagram.nodeTemplate =
    $(go.Node, "Auto",
      $(go.Shape,
        { fill: "gold" }),
      $(go.Panel, "Table",
        { defaultAlignment: go.Spot.Top, defaultColumnSeparatorStroke: "black" },
        $(go.Panel, "Table",
          { column: 0 },
          $(go.TextBlock, "List 1",
            { column: 0, margin: new go.Margin(3, 3, 0, 3),
              font: "bold 12pt sans-serif" }),
          $("PanelExpanderButton", "LIST1",
            { column: 1 }),
          $(go.Panel, "Vertical",
            { name: "LIST1", row: 1, column: 0, columnSpan: 2 },
            new go.Binding("itemArray", "list1"))
        ),
        $(go.Panel, "Table",
          { column: 1 },
          $(go.TextBlock, "List 2",
            { column: 0, margin: new go.Margin(3, 3, 0, 3),
              font: "bold 12pt sans-serif" }),
          $("PanelExpanderButton", "LIST2",
            { column: 1 }),
          $(go.Panel, "Vertical",
            { name: "LIST2", row: 1, column: 0, columnSpan: 2 },
            new go.Binding("itemArray", "list2"))
        )
      )
    );

  diagram.model = new go.GraphLinksModel([
    {
      key: 1,
      list1: [ "one", "two", "three", "four", "five" ],
      list2: [ "first", "second", "third", "fourth" ]
    }
  ]);
</code></pre>
<script>goCode("panelExpanderButton", 600, 200)</script>

<p>
A "PanelExpanderButton" is like a "TreeExpanderButton" or "SubGraphExpanderButton"
in its being a "Button" with a border Shape surrounding an icon Shape.
However, this panel binds the <a>Shape.geometryString</a> rather than the <a>Shape.figure</a>.
</p>
<pre class="lang-js" id="panelExpanderButton2"><code>
  diagram.nodeTemplate =
    $(go.Node, "Auto",
      $(go.Shape,
        { fill: "gold" }),
      $(go.Panel, "Table",
        { defaultAlignment: go.Spot.Top, defaultColumnSeparatorStroke: "black" },
        $(go.Panel, "Table",
          { column: 0 },
          $(go.TextBlock, "List 1",
            { column: 0, margin: new go.Margin(3, 3, 0, 3),
              font: "bold 12pt sans-serif" }),
          $("PanelExpanderButton", "LIST1",
            { column: 1,
              // set the two additional properties used by "PanelExpanderButton"
              // that control the shape depending on the value of GraphObject.visible
              // of the object named "LIST1"
              "_buttonExpandedFigure": "M0 0 L10 0",
              "_buttonCollapsedFigure": "M0 5 L10 5 M5 0 L5 10",
              "ButtonIcon.stroke": "blue",
              height: 16
            }),
          $(go.Panel, "Vertical",
            { name: "LIST1", row: 1, column: 0, columnSpan: 2 },
            new go.Binding("itemArray", "list1"))
        ),
        $(go.Panel, "Table",
          { column: 1 },
          $(go.TextBlock, "List 2",
            { column: 0, margin: new go.Margin(3, 3, 0, 3),
              font: "bold 12pt sans-serif" }),
          $("PanelExpanderButton", "LIST2",
            { column: 1,
              // set the two additional properties used by "PanelExpanderButton"
              // that control the shape depending on the value of GraphObject.visible
              // of the object named "LIST1"
              "_buttonExpandedFigure": "F M0 10 L5 0 10 10z",
              "_buttonCollapsedFigure": "F M0 0 L10 0 5 10z",
              "ButtonIcon.strokeWidth": 0,
              "ButtonIcon.fill": "blue"
            }),
          $(go.Panel, "Vertical",
            { name: "LIST2", row: 1, column: 0, columnSpan: 2 },
            new go.Binding("itemArray", "list2"))
        )
      )
    );

  diagram.model = new go.GraphLinksModel([
    {
      key: 1,
      list1: [ "one", "two", "three", "four", "five" ],
      list2: [ "first", "second", "third", "fourth" ]
    }
  ]);
</code></pre>
<script>goCode("panelExpanderButton2", 600, 200)</script>


<h2 id="ContextMenuButtons">ContextMenuButtons and ContextMenus</h2>
<p>
Although you can implement context menus in any way you choose, it is common to use the predefined "ContextMenuButton".
</p>
<pre class="lang-js" id="contextMenuButtons"><code>
  diagram.nodeTemplate =
    $(go.Node, "Auto",
      $(go.Shape, "Rectangle",
        { fill: "gold" }),
      $(go.TextBlock, "Use ContextMenu!",
        { margin: 5 })
    );

  diagram.nodeTemplate.contextMenu =
    $("ContextMenu",
      $("ContextMenuButton",
        $(go.TextBlock, "Shift Left"),
        { click: function(e, obj) { shiftNode(obj, -20); } }),
      $("ContextMenuButton",
        $(go.TextBlock, "Shift Right"),
        { click: function(e, obj) { shiftNode(obj, +20); } })
    );

  function shiftNode(obj, dist) {
    var adorn = obj.part;
    var node = adorn.adornedPart;
    node.diagram.commit(function(d) {
      var pos = node.location.copy();
      pos.x += dist;
      node.location = pos;
    }, "Shift");
  }

  diagram.model = new go.GraphLinksModel(
    [ { key: 1 } ] );
</code></pre>
<script>goCode("contextMenuButtons", 600, 150)</script>
<p>
For an example of defining context menus using HTML, see the <a href="../samples/customContextMenu.html">Custom ContextMenu sample</a>.
</p>

<p>
A "ContextMenuButton" is just a "Button" with a few properties set.
One of those properties is <a>GraphObject.stretch</a>, which is set to
<code>go.GraphObject.Horizontal</code> so that all of the "ContextMenuButton"s
in a "ContextMenu" will be stretch to the same width.
But you can set all of the usual properties on both its "ButtonBorder" Shape
as well as on the button itself.
</p>
<pre class="lang-js" id="contextMenuButtons2"><code>
  diagram.nodeTemplate =
    $(go.Node, "Auto",
      $(go.Shape, "Rectangle",
        { fill: "gold" }),
      $(go.TextBlock, "Use ContextMenu!",
        { margin: 5 })
    );

  diagram.nodeTemplate.contextMenu =
    $("ContextMenu",
      $("ContextMenuButton",
        {
          "ButtonBorder.fill": "yellow",
          "_buttonFillOver": "cyan",
          "_buttonFillPressed": "lime"
        },
        $(go.TextBlock, "Shift Left"),
        { click: function(e, obj) { shiftNode(obj, -20); } }
      ),
      $("ContextMenuButton",
        {
          "ButtonBorder.fill": "yellow",
          "_buttonFillOver": "cyan",
          "_buttonFillPressed": "lime"
        },
        $(go.TextBlock, "Shift Right"),
        { click: function(e, obj) { shiftNode(obj, +20); } }
      ),
      $("ContextMenuButton",
        { isEnabled: false },
        $(go.TextBlock, "Shift Right", { stroke: "gray" }),
        { click: function(e, obj) { alert("won't be alerted"); } }
      )
    );

  function shiftNode(obj, dist) {
    var adorn = obj.part;
    var node = adorn.adornedPart;
    node.diagram.commit(function(d) {
      var pos = node.location.copy();
      pos.x += dist;
      node.location = pos;
    }, "Shift");
  }

  diagram.model = new go.GraphLinksModel(
    [ { key: 1 } ] );
</code></pre>
<script>goCode("contextMenuButtons2", 600, 150)</script>

<p>
See also the fancier round context menu implemented in
<a href="../samples/radialAdornment.html">Radial Context Menu</a>.
</p>

<h2 id="CheckBoxButtons">CheckBoxButtons and CheckBoxes</h2>
<p>
A "CheckBoxButton" is a "Button" that is configured to toggle the boolean value of a data property.
By default the button is clear when the value is false and shows a check mark when the value is true,
but a great deal of customization is possible.
</p>
<p>
The first argument when defining a "CheckBoxButton" should be a string that names the data property
holding the checked state of the "CheckBoxButton".
If you do not want clicking on the button to toggle the value of a data property,
specify a data property name that is the empty string.
</p>
<p>
A "CheckBoxButton" is used in the definition of the "CheckBox" Panel, which is a convenient way to associate
any GraphObject as a label for the "CheckBoxButton".
</p>
<p>
Many examples of "CheckBox"es with various customizations are shown in the <a href="../extensions/CheckBoxes.html">CheckBoxes</a> sample.
</p>
<p>
You can find the definition of a "TriStateCheckBoxButton" in the <a href="../samples/triStateCheckBoxTree.html">Tri-State CheckBox Tree</a> sample.
</p>

<h2 id="ButtonDefinitions">Button Definitions</h2>
<p>
The implementation of all predefined buttons is provided in <a href="../extensions/Buttons.js">Buttons.js</a>
in the Extensions directory.
You may wish to copy and adapt these definitions when creating your own buttons.
</p>
<p>
Those definitions might not be an up-to-date description
of the actual standard button implementations that are in <b>GoJS</b> and used by <a>GraphObject,make</a>.
</p>
<p>
Note that the definitions of those buttons makes use of the <a>GraphObject.defineBuilder</a> static function.
That extends the behavior of <a>GraphObject,make</a> to allow the creation of fairly complex visual trees by name with optional arguments.
You can find the definitions of various kinds of controls throughout the samples and extensions, such as at:
<ul>
  <li><a href="../extensions/Buttons.js">Buttons.js</a></li>
  <li><a href="../extensions/HyperlinkText.js">HyperlinkText.js</a></li>
  <li><a href="../extensions/ScrollingTable.js">ScrollingTable.js</a></li>
  <li><a href="../extensions/ScrollingTable.js">AutoRepeatButton</a></li>
</ul>
</p>

      </div>
    </div>
  
  <div class="bg-nwoods-primary">
    <section class="max-w-screen-lg text-white container mx-auto py-2 px-12">
      <p id="version" class="leading-none mb-2 my-4">GoJS</p>
    </section>
  </div><footer class="bg-nwoods-primary text-white">
  <div class="container max-w-screen-lg mx-auto  px-8">
    <div class="w-full py-6">

        <div class="max-w-screen-lg xl:max-w-screen-xl mx-auto px-4 sm:px-6 md:px-8">
          <ul class="text-sm font-medium pb-14 sm:pb-20 grid grid-cols-1 sm:grid-cols-3 gap-y-10">
            <li class="list-none row-span-2">
              <h2 class="text-base font-semibold tracking-wide">GoJS</h2>
              <ul class="list-none space-y-4 md:space-y-1 px-0">
                <li>
                  <a href="../samples/index.html">Samples</a>
                </li>
                <li>
                  <a href="../learn/index.html">Learn</a>
                </li>
                <li>
                  <a href="../intro/index.html">Intro</a>
                </li>
                <li>
                  <a href="../api/index.html">API</a>
                </li>
                <li>
                  <a href="../changelog.html">Changelog</a>
                </li>
                <li>
                  <a href="https://github.com/NorthwoodsSoftware/GoJS">GitHub</a>
                </li>
              </ul>
            </li>
            <li class="list-none row-span-2">
              <h2 class="text-base font-semibold tracking-wide">Support</h2>
              <ul class="list-none space-y-4 md:space-y-1 px-0">
                <li>
                  <a href="https://www.nwoods.com/contact.html"
                  target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a>
                </li>
                <li>
                  <a href="https://forum.nwoods.com/c/gojs">Forum</a>
                </li>
                <li>
                  <a href="https://www.nwoods.com/app/activate.aspx?sku=gojs">Activate</a>
                </li>
                <li>
                  <a href="https://www.nwoods.com/sales/index.html"
                  target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a>
                </li>
                <li>
                  <a href="https://www.youtube.com/channel/UC9We8EoX596-6XFjJDtZIDg">Videos</a>
                </li>
              </ul>
            </li>
            <li class="list-none row-span-2">
              <h2 class="text-base font-semibold tracking-wide">Company</h2>
              <ul class="list-none space-y-4 md:space-y-1 px-0">
                <li>
                  <a href="https://www.nwoods.com">Northwoods</a>
                </li>
                <li>
                  <a href="https://www.nwoods.com/about.html">About Us</a>
                </li>
                <li>
                  <a href="https://www.nwoods.com/contact.html">Contact Us</a>
                </li>
                <li>
                  <a href="https://twitter.com/northwoodsgo">Twitter</a>
                </li>

              </ul>
            </li>
          </ul>


      <p class="text-sm text-gray-100 md:mb-6">
        Copyright 1998-2021 <a class="text-white" href="https://www.nwoods.com">Northwoods Software</a>
      </p>
    </div>
  </div>
</footer>  </body>

<script async src="https://www.googletagmanager.com/gtag/js?id=UA-1506307-5"></script> 
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date()); gtag('config', 'UA-1506307-5');
  var getOutboundLink = function(url, label) {
    gtag('event', 'click', {
      'event_category': 'outbound',
      'event_label': label,
      'transport_type': 'beacon'
    });
  }

  // topnav
  var topButton = document.getElementById("topnavButton");
  var topnavList = document.getElementById("topnavList");
  topButton.addEventListener("click", function() {
    this.classList.toggle("active");
    topnavList.classList.toggle("hidden");
    document.getElementById("topnavOpen").classList.toggle("hidden");
    document.getElementById("topnavClosed").classList.toggle("hidden");
  });
</script>
  <script src="../assets/js/prism.js"></script>
  <script src="../release/go.js"></script>
  <script src="../assets/js/goDoc.js"></script>
  <script>
    document.addEventListener("DOMContentLoaded", function() {
      if (window.go) document.getElementById('version').textContent = "GoJS version " + go.version;
      if (window.goDoc) window.goDoc();
      var d = window.diagrams;
      for (var i = 0; i < d.length; i++) {
        var dargs = d[i];
        goCodeExecute(dargs[0], dargs[1], dargs[2], dargs[3], dargs[4]);
      }
      if (window.extra) window.extra();
    });
  </script>
</html>
